package com.buluo.service.impl

import com.buluo.service.BaseMongoService
import com.m1905hd.common.util.Page
import com.mongodb.BasicDBObject
import com.mongodb.DBCollection
import com.mongodb.DBCursor
import com.mongodb.DBObject
import org.bson.types.ObjectId
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.data.mongodb.core.MongoTemplate
import org.springframework.util.StringUtils

/**
 *
 * @author weiwei.huang
 * @email ihuangweiwei@163.com
 * @date 15/4/3
 */
abstract class BaseMongoServiceImpl implements BaseMongoService {

    @Autowired
    MongoTemplate hdMongoTemplate

    @Override
    Page list(BasicDBObject query, BasicDBObject sort, BasicDBObject returnFiled, int page, int size) {
        int total = getColl().count(query)
        if (size < 0 || size >= 20) {
            size = 20;
        }
        if (page <= 0) {
            page = 1;
        }
        Page p = new Page(total, page, size);
        def data = new ArrayList()
        p.data = data
        if (returnFiled == null) {
            returnFiled = new BasicDBObject()
        }
        DBCursor cursor = getColl().find(query, returnFiled).batchSize(100).sort([_id: -1] as BasicDBObject).
                limit(size).skip((page - 1) * size)
        if (sort) {
            cursor = getColl().find(query, returnFiled).batchSize(100).sort([_id: -1] as BasicDBObject).sort(sort).
                    limit(size).skip((page - 1) * size)
        }
        while (cursor.hasNext()) {
            def info = cursor.next()
            if (info._id instanceof ObjectId) {
                if (info.id == null) {
                    info.id = info._id.toString()
                }
            } else {
                if (info.id == null) {
                    info.id = info._id
                }
            }
            data.add(info)
        }
        return p
    }

    @Override
    DBObject findOne(Object _id) {
        return getColl().findOne([_id: _id] as BasicDBObject)
    }

    @Override
    boolean update(Object id, DBObject object) {
        def errors = getColl().update([_id: id] as BasicDBObject, ['$set': object] as BasicDBObject, true, true).getError()
        if (StringUtils.isEmpty(errors)) {
            return true
        }
        return false
    }

    @Override
    boolean save(DBObject object) {
        def errors = getColl().save(object as BasicDBObject).getError()
        return errors.equals("")
    }

    def count(BasicDBObject query){
        return getColl().count(query)
    }

    @Override
    List<DBObject> list(List<Integer> ids) {
        if (ids == null || ids.isEmpty()) {
            return Collections.emptyList()
        }
        DBCursor cursor = getColl().find([_id: ['$in': ids] as BasicDBObject] as BasicDBObject)
        def list = [] as ArrayList
        def map = new HashMap()
        while (cursor.hasNext()) {
            def info = cursor.next()
            if (info.id == null) {
                info.id = info._id
            }

            map.put(info._id as Integer, info)
        }
        ids.each {
            if (map.get(it)) {
                list.add(map.get(it))
            }
        }
        return list
    }


    @Override
    boolean del(Object id) {
        getColl().remove([_id: id] as BasicDBObject).getError().equals("")
    }

    abstract DBCollection getColl()


    synchronized Integer getCurrentId() {
        def idsColl = hdMongoTemplate.getCollection("inc_ids")
        def info = idsColl.findOne([name: getColl().getName()] as BasicDBObject)
        if (info) {
            idsColl.update([_id: info._id] as BasicDBObject, ['$inc': [id: 1] as BasicDBObject] as BasicDBObject)
            return info.id + 1
        }
        info = getColl().findOne(new BasicDBObject(), [_id: 1] as BasicDBObject, [_id: -1] as BasicDBObject)
        int id = 9000000
        if (info) {
            id = info._id
        }
        idsColl.save([name: getColl().getName(), id: ++id] as BasicDBObject)
        return id
    }

    List find(BasicDBObject query){
        DBCursor cursor = getColl().find(query)
        List list = new ArrayList()
        while (cursor.hasNext()){
            list.add(cursor.next())
        }
        return list
    }
}
